package com.ares.comparer.Controller;

import com.ares.comparer.config.Result;
import com.ares.comparer.utils.ImageCompare;
import com.github.romankh3.image.comparison.ImageComparison;
import com.github.romankh3.image.comparison.ImageComparisonUtil;
import com.github.romankh3.image.comparison.model.ImageComparisonResult;
import de.redsix.pdfcompare.PdfComparator;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.PumpStreamHandler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;

import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.Array;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@RequestMapping("/compare")
@RestController
public class Comparer {
    @Value("${comparePrefix}")
    private String comparePrefix;
    private static final String PATH = "C:\\ideaProjects\\comparer\\src\\main\\resources\\";
    private static final String PYTHON_FILE = PATH + "py\\compareImages.py";
    private static final String SAVE_PATH = " " + PATH + "compareResults\\";

    @PostMapping("/image")
    @ResponseBody
    public Result uploadImage(@RequestParam Integer threshold, MultipartFile[] files) throws Exception {
        ArrayList params = new ArrayList();
        ArrayList fileNames = new ArrayList();
        String fullFileName = "请同时上传两张需要对比的图片";
        String fileName = "";
        HashMap<String, String> res = new HashMap<>();
        if (files != null && files.length == 2) {
            //自动获取文件名
            /*for (MultipartFile file : files) {
                params.add(saveFile(file, null));
                fileNames.add(getFileNameMap(file.getOriginalFilename()).get("name"));
            }*/
            // 指定文件名
            for (int i = 0; i < files.length; i++) {
                String fname = "image" + i;
                params.add(saveFile(files[i], fname));
                fileNames.add(fname);
            }
            fullFileName = compareImages(params.get(0).toString(), params.get(1).toString(), threshold);
            fileName = getFileName(fullFileName);
            String[] temps = {params.get(0).toString(), params.get(1).toString()};
            removeTempFile(temps);
        }

        res.put("fullFileName", fullFileName);
        res.put("fileName", comparePrefix + fileName);
        return Result.success(res);
    }

    @PostMapping("/image1")
    @ResponseBody
    public Result uploadImage1(@RequestParam Integer threshold, MultipartFile[] files) throws Exception {
        ArrayList params = new ArrayList();
        ArrayList fileNames = new ArrayList();
        String fullFileName = "请同时上传两张需要对比的图片";
        String fileName = "";
        HashMap<String, String> res = new HashMap<>();
        if (files != null && files.length == 2) {
            //自动获取文件名
            /*for (MultipartFile file : files) {
                params.add(saveFile(file, null));
                fileNames.add(getFileNameMap(file.getOriginalFilename()).get("name"));
            }*/
            // 指定文件名
            for (int i = 0; i < files.length; i++) {
                String fname = "image" + i;
                params.add(saveFile(files[i], fname));
                fileNames.add(fname);
            }
            BufferedImage expectedImage = ImageComparisonUtil.readImageFromResources(params.get(0).toString());
            BufferedImage actualImage = ImageComparisonUtil.readImageFromResources(params.get(1).toString());

            fileName = fileNames.get(0).toString() + "_" + fileNames.get(1).toString() + "_diff.png";
            fullFileName = getSavePath() + fileName;
            File resultDestination = new File( fullFileName );

            ImageComparison imageComparison = new ImageComparison(expectedImage, actualImage);
            imageComparison.setThreshold(threshold);
            imageComparison.setRectangleLineWidth(5);
            imageComparison.setDifferenceRectangleFilling(true, 0);
            ImageComparisonResult imageComparisonResult = imageComparison.compareImages();
            ImageComparisonUtil.saveImage(resultDestination, imageComparisonResult.getResult());
            String[] temps = {params.get(0).toString(), params.get(1).toString()};
            removeTempFile(temps);
        }

        res.put("fullFileName", fullFileName);
        res.put("fileName", comparePrefix + fileName);
        return Result.success(res);
    }


    @PostMapping("/image2")
    @ResponseBody
    public Result uploadImage2(@RequestParam Integer threshold, MultipartFile[] files) throws Exception {
        ArrayList params = new ArrayList();
        ArrayList fileNames = new ArrayList();
        String fullFileName = "请同时上传两张需要对比的图片";
        String fileName = "";
        HashMap<String, String> res = new HashMap<>();
        if (files != null && files.length == 2) {
            //自动获取文件名
            /*for (MultipartFile file : files) {
                params.add(saveFile(file, null));
                fileNames.add(getFileNameMap(file.getOriginalFilename()).get("name"));
            }*/
            // 指定文件名
            for (int i = 0; i < files.length; i++) {
                String fname = "image" + i;
                params.add(saveFile(files[i], fname));
                fileNames.add(fname);
            }
            ImageCompare imageCompare = new ImageCompare(params.get(0).toString(), params.get(1).toString(), threshold, getSavePath());
//            imageCompare.setImageSizeNuance(80);
//            imageCompare.setIgnoreImageSizeNuance(false);
            try {
                fullFileName = imageCompare.compare();
                fileName = fileNames.get(0).toString() + "_" + fileNames.get(1).toString() + "_diff.png";
                String[] temps = {params.get(0).toString(), params.get(1).toString()};
                removeTempFile(temps);
            }catch (Exception e) {
                System.out.println(e);
                fullFileName = e.toString();
            }
        }

        res.put("fullFileName", fullFileName);
        res.put("fileName", comparePrefix + fileName);
        return Result.success(res);
    }


    @PostMapping("/pdf")
    @ResponseBody
    public Result uploadPdf(MultipartFile[] files) throws Exception {
        ArrayList params = new ArrayList();
        ArrayList fileNames = new ArrayList();

        String fullFileName = "请同时上传两份需要对比的PDF文件";
        String fileName = "";
        HashMap<String, String> res = new HashMap<>();
        if (files != null && files.length == 2) {
            // 自动获取文件名
            /*for (MultipartFile file : files) {
                params.add(saveFile(file, null));
                fileNames.add(getFileNameMap(file.getOriginalFilename()).get("name"));
            }*/
            // 指定文件名
            for (int i = 0; i < files.length; i++) {
                String fname = "pdf" + i;
                params.add(saveFile(files[i], fname));
                fileNames.add(fname);
            }
            fileName = fileNames.get(0).toString() + "_" + fileNames.get(1).toString() + "_diff";
            new PdfComparator(params.get(0).toString(), params.get(1).toString()).compare().writeTo(getSavePath() + fileName);

            String fileNameWithType = fileName + ".pdf";
            fullFileName = getSavePath() + fileNameWithType;
            res.put("fullFileName", fullFileName);
            res.put("fileName", comparePrefix + fileNameWithType);
            String[] temps = {params.get(0).toString(), params.get(1).toString()};
            removeTempFile(temps);
        }
        return Result.success(res);
    }

    public String saveFile(MultipartFile file, String fileName) {
        if (file.isEmpty()) {
            return "文件为空！";
        }
        if(fileName == null) fileName = file.getOriginalFilename();
        String fileType = getFileNameMap(file.getOriginalFilename()).get("type");
        String fileNameWithType = fileName + "." + fileType;
        try {
//            File saveFile = new File(SAVE_PATH, fileName);
            File saveFile = new File(getSavePath(), fileNameWithType);
            File parentFile = saveFile.getParentFile();
            if (!parentFile.exists()) {
                parentFile.mkdir();
            }
            file.transferTo(saveFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
//        return SAVE_PATH + fileName; // 返回重命名后的文件名
        return getSavePath() + fileNameWithType; // 返回重命名后的文件名
    }

    public String compareImages(String iamge1, String iamge2, Integer threshold) {
        final String line = "python";
        final CommandLine cmdLine = CommandLine.parse(line);
//        cmdLine.addArguments(new String[]{PYTHON_FILE, iamge1, iamge2, SAVE_PATH, threshold.toString()});
        cmdLine.addArguments(new String[]{getPythonFilePath(), iamge1, iamge2, getSavePath(), threshold.toString()});

        try (final ByteArrayOutputStream diffImagePath = new ByteArrayOutputStream()) {
            final PumpStreamHandler streamHandler = new PumpStreamHandler(diffImagePath);

            final DefaultExecutor executor = new DefaultExecutor();
            executor.setStreamHandler(streamHandler);

            final int exitCode = executor.execute(cmdLine);

            String imagePath = diffImagePath.toString().trim();

            System.out.println("调用Python脚本的执行结果: " + exitCode);
            System.out.println("对比结果图路径: " + imagePath);
            return imagePath;
        } catch (final IOException e) {
            System.out.println("调用Python脚本出错" + e);
        }
        return "";
    }

    public String getPath() {
        ApplicationHome applicationHome = new ApplicationHome(this.getClass());
        return  Paths.get(applicationHome.getDir().toURI()).getRoot().toString();
    }

    public String getResourcesPath() {
        ApplicationHome applicationHome = new ApplicationHome(this.getClass());
        String root = applicationHome.getDir().getParentFile().getParentFile().getAbsolutePath();
        // 保存目录位置根据项目需求可随意更改
        return  root + "\\src\\main\\resources\\";
    }

    public String getSavePath() {
        return getPath() + "compareResults\\";
    }

    public String getPythonFilePath() {
        return getResourcesPath() + "py\\compareImages.py";
    }

    /*public String getRootPath() {
        return Paths.get(PATH).toString();
    }

    public String getSavePath() {
        return Paths.get(SAVE_PATH).toString();
    }

    public String getPythonFilePath() {
        return Paths.get(PYTHON_FILE).toString();
    }*/

    public String getFileName(String url) {
        return Paths.get(url).getFileName().toString();
    }
    public Map<String, String> getFileNameMap(String url) {
        Path path = Paths.get(url);
        HashMap<String, String> map = new HashMap<>();
        String[] fn = path.getFileName().toString().split("\\.");
        map.put("name", fn[0]);
        map.put("type", fn[1]);
        return map;
    }

    public void removeTempFile(String[] paths) {
        for (String path : paths) {
            try {
                Files.delete(Paths.get(path));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
